package com.microservice.salmon.weixin.utils;

import com.microservice.salmon.weixin.domain.config.WeiXinPropertiesConfig;
import com.microservice.salmon.weixin.domain.menu.Menu;
import com.microservice.salmon.weixin.domain.menu.MenuResult;
import com.microservice.salmon.weixin.domain.support.WeiXinAuth;
import com.microservice.salmon.weixin.domain.ticket.AccessToken;
import com.microservice.salmon.weixin.domain.ticket.Ticket;
import com.microservice.salmon.weixin.domain.ticket.WeiXinTicket;
import com.microservice.salmon.weixin.store.WeiXinTicketStore;
import com.salmon.common.utils.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.time.Instant;

@Component
public class WeiXinUtils {

    public static final String MESSAGE_TEXT = "text";
    public static final String MESSAGE_NEWS = "news";
    public static final String MESSAGE_IMAGE = "image";
    public static final String MESSAGE_VOICE = "voice";
    public static final String MESSAGE_MUSIC = "music";
    public static final String MESSAGE_VIDEO = "video";
    public static final String MESSAGE_LINK = "link";
    public static final String MESSAGE_LOCATION = "location";
    public static final String MESSAGE_EVNET = "event";
    public static final String MESSAGE_SUBSCRIBE = "subscribe";
    public static final String MESSAGE_UNSUBSCRIBE = "unsubscribe";
    public static final String MESSAGE_CLICK = "CLICK";
    public static final String MESSAGE_VIEW = "VIEW";
    public static final String MESSAGE_SCANCODE= "scancode_push";

    private static final String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s";

    private static final String UPLOAD_URL = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s";

    private static final String CREATE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token=%s";

    private static final String QUERY_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token=%s";

    private static final String DELETE_MENU_URL = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=%s";

    //POST
    private static final String QR_CODE_URL = "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=%s";

    //GET
    private static final String GET_QR_CODE_URL = "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=%s";

    //GET方式请求获得jsapi_ticket
    private static final String GET_JS_SDK_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi";
    private static final String JS_SDK_TICKET_KEY = "WX_JS_SDK_KEY";

    //http请求方式: GET
    private static final String GET_WX_CARD_TICKET_URL = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=wx_card";
    private static final String WX_CARD_KEY = "WX_CARD_KEY";

    private RestTemplate restTemplate;

    private WeiXinPropertiesConfig weixinConfig;

    private WeiXinTicketStore weiXinTicketStore;

    public WeiXinUtils(WeiXinPropertiesConfig weixinConfig, WeiXinTicketStore weiXinTicketStore, RestTemplate restTemplate) {
        this.weixinConfig = weixinConfig;
        this.weiXinTicketStore = weiXinTicketStore;
        this.restTemplate = restTemplate;
    }

    /**
     * 获取accessToken, 正式应用时请把AccessToken进行缓存， 默认 2小时过期
     */
    public AccessToken getAccessToken() {
        Ticket token = weiXinTicketStore.getWeiXinTicketFromStore(weixinConfig.getAppId());
        if(token == null) {
            String url = String.format(ACCESS_TOKEN_URL, weixinConfig.getAppId(), weixinConfig.getAppSecret());
            token = restTemplate.getForObject(url, AccessToken.class);
            weiXinTicketStore.storeWeiXinTicket(weixinConfig.getAppId(),token);
        }
        return (AccessToken)token;
    }

    public WeiXinTicket getJsSdkTicket() {
        return getWeiXinTicket(GET_JS_SDK_TICKET_URL, JS_SDK_TICKET_KEY);
    }

    public WeiXinTicket getWxCardTicket() {
        return getWeiXinTicket(GET_WX_CARD_TICKET_URL, WX_CARD_KEY);
    }


    public WeiXinAuth getWeiXinJsSDKAuth(String url) {
        String nonceStr = RandomStringUtils.randomAlphanumeric(16);
        String js_sdk_privilege = "jsapi_ticket=%s&noncestr=%s&timestamp=%s&url=%s";
        long timestamp = Instant.now().getEpochSecond();
        WeiXinTicket ticket = getJsSdkTicket();
        String signature = DigestUtils.getSha1(String.format(js_sdk_privilege,ticket.getTicket(),nonceStr,timestamp, url));
        return new WeiXinAuth(weixinConfig.getAppId(),nonceStr,signature, timestamp);
    }

    private WeiXinTicket getWeiXinTicket(String url, String key) {
        Ticket ticket = weiXinTicketStore.getWeiXinTicketFromStore(key);
        if(ticket == null) {
            AccessToken accessToken = getAccessToken();
            ticket = restTemplate.getForObject(String.format(url, accessToken.getAccessToken()), WeiXinTicket.class);
            weiXinTicketStore.storeWeiXinTicket(key, ticket);
        }
        return (WeiXinTicket)ticket;
    }

    /**
     * 创建菜单
     * @param accessToken accessToken
     * @param menu 序列化后的 menu字符串
     * @return
     */
    public MenuResult createMenu(String accessToken, String menu) {
        String url = String.format(CREATE_MENU_URL, accessToken);
        HttpEntity<String> formEntity = new HttpEntity<>(menu);
        return restTemplate.postForObject(url, formEntity, MenuResult.class);
    }

    /**
     * 查询菜单
     * @param accessToken accessToken
     * @return
     */
    public Menu queryMenu(String accessToken) {
        String url =  String.format(QUERY_MENU_URL, accessToken);
        return restTemplate.getForObject(url, Menu.class);
    }
    /**
     * 删除菜单
     * @param accessToken accessToken
     * @return
     */
    public MenuResult deleteMenu(String accessToken) {
        String url = String.format(DELETE_MENU_URL, accessToken);
        return restTemplate.getForObject(url, MenuResult.class);
    }


}
